package org.jfinanceobserver.persistence.jpa.controller;

import java.util.HashMap;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;

/**
 * This Class is the abstract class to JPA controller
 *
 * @param <T> $Author: r78v10a07@gmail.com $ $LastChangedDate: 2013-02-11 13:03:43 +0000 (Mon, 11 Feb 2013) $ $LastChangedRevision: 2 $
 * @since Nov 17, 2010
 */
public abstract class AbstractJpaController<T> {

    /**
     * This method return the Persistence EntityManager
     *
     * @return the Persistence EntityManager
     */
    public abstract EntityManager getEntityManager();

    /**
     * This method perform the NamedQuery over the selected entity
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @return a Entity List
     */
    public List useNamedQuery(String nameQuery) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity in a defined
     * range
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param range is the first number is the first result and the second
     * number is the max results
     * @return a Entity List
     */
    public List useNamedQuery(String nameQuery, int[] range) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity with defined
     * parameters
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @return a Entity List
     */
    public List useNamedQuery(String nameQuery, HashMap<String, Object> parameters) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity with defined
     * parameters in a defined range
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @param range is the first number is the first result and the second
     * number is the max results
     * @return a Entity List
     */
    public List useNamedQuery(String nameQuery, HashMap<String, Object> parameters, int[] range) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);

        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity with a single
     * result
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @return a Entity List
     */
    public Object useNamedQuerySingleResult(String nameQuery) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);
        Object result = q.getSingleResult();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity with a single
     * result with defined parameters
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @return a Entity List
     */
    public Object useNamedQuerySingleResult(String nameQuery, HashMap<String, Object> parameters) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        Object result = q.getSingleResult();
        em.close();
        return result;
    }

    /**
     * This method perform the NamedQuery over the selected entity using the
     * executeUpdate sentence
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @return a Entity List
     */
    public int useNamedQueryExecuteUpdate(String nameQuery) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);
        int i = q.executeUpdate();
        em.close();
        return i;
    }

    /**
     * This method perform the NamedQuery over the selected entity with a single
     * result with defined parameters using the executeUpdate sentence
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @return a Entity List
     */
    public int useNamedQueryExecuteUpdate(String nameQuery, HashMap<String, Object> parameters) {
        EntityManager em = getEntityManager();
        Query q = em.createNamedQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        int i = q.executeUpdate();
        em.close();
        return i;
    }

    /**
     * This method perform the NamedQuery over the selected entity using the
     * executeUpdate sentence
     *
     * @param sqlQuery is the NamedQuery defined into the Entity
     * @return a Entity List
     */
    public int useCreateQueryExecuteUpdate(String sqlQuery) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery(sqlQuery);
        int i = q.executeUpdate();
        em.close();
        return i;
    }

    /**
     * This method create and perform the NamedQuery over the selected entity
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @return a Entity List
     */
    public List createNamedQuery(String nameQuery) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery(nameQuery);
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method create and perform the NamedQuery over the selected entity
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param range is the first number is the first result and the second
     * number is the max results
     * @return a Entity List
     */
    public List createNamedQuery(String nameQuery, int[] range) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery(nameQuery);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method create and perform the NamedQuery over the selected entity
     * with defined parameters
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @return a Entity List
     */
    public List createNamedQuery(String nameQuery, HashMap<String, Object> parameters) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        List result = q.getResultList();
        em.close();
        return result;
    }

    /**
     * This method create and perform the NamedQuery over the selected entity
     * with defined parameters
     *
     * @param nameQuery is the NamedQuery defined into the Entity
     * @param parameters is the map for parameter --> value into the nameQuery
     * @param range is the first number is the first result and the second
     * number is the max results
     * @return a Entity List
     */
    public List createNamedQuery(String nameQuery, HashMap<String, Object> parameters, int[] range) {
        EntityManager em = getEntityManager();
        Query q = em.createQuery(nameQuery);

        for (String key : parameters.keySet()) {
            q.setParameter(key, parameters.get(key));
        }
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        List result = q.getResultList();
        em.close();
        return result;
    }
}
